﻿//-----------------------------------------------------------------------------------------------------------
// Wbfs Engine (WBFSe) Project by Omega Frost 
// http://wbfse.codeplex.com/
//
// WBFSe is Licensed under the terms of the 
// Microsoft Reciprocal License (Ms-RL)
//-----------------------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using WBFSe.Attributes;

namespace WBFSe.Data
{
    /// <summary>
    /// Disc's filesystem node
    /// </summary>
    public class FileSystemNode : IComparer<FileSystemNode>
    {
        // Variables

        private string name;
        private long offset;
        private long size;
        private int partition;
        private FileSystemAttributes attributes;
        private List<FileSystemNode> nodes;

        // Methods

        /// <summary>
        /// Node name
        /// </summary>
        public String Name
        {
            get { return this.name; }
        }

        /// <summary>
        /// The offset of the current file
        /// </summary>
        public long PartitionOffset
        {
            get { return this.offset; }
        }

        /// <summary>
        /// The size of the current file
        /// </summary>
        public long Size
        {
            get { return this.size; }
        }

        /// <summary>
        /// The partition index
        /// </summary>
        public int Partition
        {
            get { return this.partition; }
        }

        /// <summary>
        /// Child nodes
        /// </summary>
        public IList<FileSystemNode> Nodes
        {
            get { return this.nodes.AsReadOnly(); }
        }

        /// <summary>
        /// FileSystem attributes
        /// </summary>
        public FileSystemAttributes Attributes
        {
            get { return this.attributes; }
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="name">Node name</param>
        internal FileSystemNode(String name)
        {
            this.name = name;
            this.nodes = new List<FileSystemNode>();
        }

        /// <summary>
        /// Adds a children node
        /// </summary>
        /// <param name="node">Node</param>
        internal void AddNode(FileSystemNode node)
        {
            int p = this.nodes.BinarySearch(node, this);
            if (p >= 0) throw new ArgumentException("Child node already exists");
            this.nodes.Insert(~p, node);
            this.attributes |= FileSystemAttributes.Directory;
        }

        /// <summary>
        /// Finds a node
        /// </summary>
        /// <param name="name">Node name</param>
        /// <returns>Sub-node or null</returns>
        public FileSystemNode FindNode(String name)
        {
            FileSystemNode node = new FileSystemNode(name);
            int p = this.nodes.BinarySearch(node, this);
            if (p >= 0) return this.nodes[p];
            else return null;
        }

        /// <summary>
        /// Sets the offset and the size of the file
        /// </summary>
        /// <param name="offset">The relative position of the file</param>
        /// <param name="size">The size of the file</param>
        internal void SetFileAttributes(int partition, long offset, 
            long size, bool system, bool encrypted)
        {
            this.partition = partition;
            this.offset = offset;
            this.size = size;

            this.attributes = FileSystemAttributes.None;
            if (system) this.attributes |= FileSystemAttributes.System;
            if (encrypted) this.attributes |= FileSystemAttributes.Encrypted;
        }

        /// <summary>
        /// Compares 2 nodes
        /// </summary>
        /// <param name="x">First node</param>
        /// <param name="y">Second node</param>
        /// <returns>Comparison</returns>
        public int Compare(FileSystemNode x, FileSystemNode y)
        {
            return x.name.CompareTo(y.name);
        }

        /// <summary>
        /// Returns the name of the node
        /// </summary>
        /// <returns>The name of the node</returns>
        public override string ToString()
        {
            return this.name;
        }
    }
}
